package webmote.server;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;

import webmote.client.Constants;

public class SessionImages implements Serializable, Constants {

	private static final long serialVersionUID = 2990499621846259677L;

	private int idCounter;
    private Tile[][] tiles;

    public static SessionImages getSessionImages(HttpSession session) {
        SessionImages sessionImages = (SessionImages) session.getAttribute("SESSION_IMAGES");
        if (sessionImages == null) {
            sessionImages = new SessionImages();
            session.setAttribute("SESSION_IMAGES", sessionImages);
        }
        return sessionImages;
    }

    public void setScreenCapture(BufferedImage screenCapture) {
        int cols = screenCapture.getWidth() / TILE_SIZE;
        int rows = screenCapture.getHeight() / TILE_SIZE;

        if (tiles == null) {
            initTiles(screenCapture, rows, cols);
        } else if (tiles.length != rows || tiles[0].length != cols) {
            initTiles(screenCapture, rows, cols);
        } else {
            for (int row = 0; row < tiles.length; row++) {
                for (int col = 0; col < tiles[row].length; col++) {
                    tiles[row][col].setBufferedImage(screenCapture.getSubimage(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE));
                }
            }
        }
    }

    public int[][] getTilesIds() {
        int[][] ids = new int[tiles.length][];
        for (int row = 0; row < tiles.length; row++) {
            ids[row] = new int[tiles[row].length];
            for (int col = 0; col < tiles[row].length; col++) {
                ids[row][col] = tiles[row][col].id;
            }
        }
        return ids;
    }

    public byte[] getTileImage(int tileId) {
        for (int row = 0; row < tiles.length; row++) {
            for (int col = 0; col < tiles[row].length; col++) {
                if (tiles[row][col].id == tileId) {
                    return tiles[row][col].image;
                }
            }
        }
        return null;
    }

    private void initTiles(BufferedImage screenCapture, int rows, int cols) {
        tiles = new Tile[rows][cols];
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                tiles[row][col] = new Tile(screenCapture.getSubimage(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE));
            }
        }
    }

    private int createTileId() {
        return idCounter++;
    }

    private class Tile implements Serializable {
		private static final long serialVersionUID = 8947157180575780544L;

		protected int id;
        private byte[] image;

        private Tile(BufferedImage image) {
            setBufferedImage(image);
        }

        public byte[] getImage() {
            return image;
        }

        private void setBufferedImage(BufferedImage bufferedImage) {
            byte[] oldImage = image;

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                ImageIO.write(bufferedImage, "jpg", out);
            } catch (IOException e) {
                e.printStackTrace();
            }
            image = out.toByteArray();

            if (oldImage == null || oldImage.length != image.length) {
                id = createTileId();
            } else {
                for (int index = 0; index < image.length; index++) {
                    if (oldImage[index] != image[index]) {
                        id = createTileId();
                        break;
                    }
                }
            }
        }
    }

}
